/**
 *  Serponix is an arcade game in focus to multiplayer based on the classic game Snake.
 *  Copyright (C) 2010 - 2011  Daniel Vala
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License,
 *  or  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.

 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  If you have any question do not hesitate to contact author
 *  on e-mail address: danielvala42@gmail.com
 */
package com.serponix.ai;

import com.serponix.game.Direction;
import com.serponix.game.GameModel;
import com.serponix.game.Player;
import com.serponix.game.Snake;
import com.serponix.game.objektyNaPlose.VecNaPolicku;
import java.util.Random;

/**
 * @author Daniel Vala
 */
public class Movement {

	/**
	 * Turn on one or the other side randomly.
	 */
	protected static void turnRandomly(GameModel gameModel, Player player) {
		int random = 1 + new Random().nextInt(2);
		if (player.getSnake().getSmer() == Direction.UP || player.getSnake().getSmer() == Direction.DOWN) {
			switch (random) {
				case 1:
					changeSmer(gameModel, player, Direction.LEFT);
					break;
				case 2:
					changeSmer(gameModel, player, Direction.RIGHT);
					break;
			}
		} else if (player.getSnake().getSmer() == Direction.LEFT || player.getSnake().getSmer() == Direction.RIGHT) {
			switch (random) {
				case 1:
					changeSmer(gameModel, player, Direction.UP);
					break;
				case 2:
					changeSmer(gameModel, player, Direction.DOWN);
					break;
			}
		}
	}

	/**
	 * Player change his direction to the given one...
	 *
	 * @param gameModel
	 * @param player
	 * @param smer
	 */
	protected static boolean changeSmer(GameModel gameModel, Player player, Direction smer) {
		if (isSthInExpectedMove(gameModel, player.getSnake(), smer)) {
			return false;
		}
		player.getSnake().setVlastnostObraceneKlavesy(true);

		// if snake is drunk, only one from 6 cases turn the right way
		// other 5 cases turns excactly the other way
		if (player.getSnake().isVlastnostObraceneKlavesy() && (!RandomUtil.nahoda(6))) {
			player.changeSmer(Direction.obratSmer(smer));
		} else {
			player.changeSmer(smer);
		}
		return true;
	}

	/**
	 * Return if something is in expected move of the given snake.
	 * In other words, if snake want to turn left and this method return false, snake can safely turn left without be killed.
	 *
	 * @param gameModel    Model of the game.
	 * @param snake        Snake, which want to move.
	 * @param expectedMove Expected direction of the snake.
	 * @return True, if something is in expected move of the given snake. False if place is free and secure to move.
	 */
	protected static boolean isSthInExpectedMove(GameModel gameModel, Snake snake, Direction expectedMove) {
		boolean isSthInExpectedMove = false;
		switch (expectedMove) {
			case UP:
				if (getVecNadHadem(gameModel, snake) != null) {
					isSthInExpectedMove = true;
				}
				break;
			case DOWN:
				if (getVecPodHadem(gameModel, snake) != null) {
					isSthInExpectedMove = true;
				}
				break;
			case LEFT:
				if (getVecVlevoOdHada(gameModel, snake) != null) {
					isSthInExpectedMove = true;
				}
				break;
			case RIGHT:
				if (getVecVpravoOdHada(gameModel, snake) != null) {
					isSthInExpectedMove = true;
				}
				break;
		}
		return isSthInExpectedMove;
	}

	protected static VecNaPolicku getVecVpravoOdHada(GameModel gameModel, Snake snake) {
		return gameModel.getObjektNaHerniPlose(snake.getX() + 1, snake.getY());
	}

	protected static VecNaPolicku getVecVlevoOdHada(GameModel gameModel, Snake snake) {
		return gameModel.getObjektNaHerniPlose(snake.getX() - 1, snake.getY());
	}

	protected static VecNaPolicku getVecPodHadem(GameModel gameModel, Snake snake) {
		return gameModel.getObjektNaHerniPlose(snake.getX(), snake.getY() + 1);
	}

	protected static VecNaPolicku getVecNadHadem(GameModel gameModel, Snake snake) {
		return gameModel.getObjektNaHerniPlose(snake.getX(), snake.getY() - 1);
	}
}